package com.personal.core.utils;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.MethodDescriptor;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * 内省工具类
 * @author cuibo
 *
 */
public class IntrospectorUtil
{
    /**
     * 获取属性描述
     * @param clazz
     * @return
     * @throws IntrospectionException
     */
    public static PropertyDescriptor[] getPropertyDescriptors(Class<?> clazz) throws IntrospectionException
    {
        BeanInfo beanInfo = Introspector.getBeanInfo(clazz);
        return beanInfo.getPropertyDescriptors();
    }
    
    /**
     * 获取方法描述
     * @param clazz
     * @return
     * @throws IntrospectionException
     */
    public static MethodDescriptor[] getMethodDescriptors(Class<?> clazz) throws IntrospectionException
    {
        BeanInfo beanInfo = Introspector.getBeanInfo(clazz);
        return beanInfo.getMethodDescriptors();
    }
    
    /**
     * 获取对应的方法
     * @param clazz
     * @param methodName
     * @param paramTypes
     * @return
     */
    public static Method getDeclaredMethod(Class<?> clazz, String methodName, Class<?>[] paramTypes)
    {
        try
        {
            return clazz.getDeclaredMethod(methodName, paramTypes);
        } catch (NoSuchMethodException ex)
        {
            if (clazz.getSuperclass() != null)
			{
				return getDeclaredMethod(clazz.getSuperclass(), methodName, paramTypes);
			}
        }
        return null;
    }
    
    /**
     * 执行指定的方法
     * @param clazz
     * @param object
     * @param methodName
     * @param paramTypes   参数类型数组
     * @param paramValues  参数值数组（和参数类型数组一一对应）
     * @return
     * @throws InvocationTargetException 
     * @throws IllegalAccessException 
     * @throws IllegalArgumentException 
     */
    public static Object invokeMethod(Class<?> clazz, Object object, String methodName, Class<?>[] paramTypes, Object[] paramValues) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException
    {
        Method method = getDeclaredMethod(clazz, methodName, paramTypes);
        if (method == null)
        {
            return null;
        }
        return method.invoke(object, paramValues);
    }

    
    /**
     * 设置属性值
     * @param propName
     * @param objIn
     * @return
     * @throws IllegalArgumentException
     * @throws IllegalAccessException
     * @throws InvocationTargetException
     * @throws IntrospectionException
     */
    public static Object getPropertyValue(String propName, Object objIn) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException, IntrospectionException
    {
        if (objIn == null)
        {
            return null;
        }
        Method method = getPropertyGetMethod(propName, objIn.getClass());
        if (method == null)
        {
            return null;
        }
        return method.invoke(objIn, new Object[0]);
    }
    
    /**
     * 获取属性的类型
     * @param propName
     * @param objIn
     * @return
     * @throws IntrospectionException
     */
    public static Class<?> getPropertyType(String propName, Class<?> objIn) throws IntrospectionException
    {
        PropertyDescriptor pd = new PropertyDescriptor(propName, objIn);
        return pd.getPropertyType();
    }
    
    /**
     * 设置属性值
     * @param propName
     * @param objIn
     * @param setValue
     * @throws IllegalArgumentException
     * @throws IllegalAccessException
     * @throws InvocationTargetException
     * @throws IntrospectionException
     */
    public static void setPropertyValue(String propName, Object objIn, Object setValue) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException, IntrospectionException
    {
        if (objIn == null)
        {
            return;
        }
        Method method = getPropertySetMethod(propName, objIn.getClass());
        if (method == null)
        {
            return;
        }
        method.invoke(objIn, setValue);
    }


    /**
     * 获取propName的Setter
     * @param propName
     * @param clazz
     * @return
     * @throws IntrospectionException
     */
    public static Method getPropertySetMethod(String propName, Class<?> clazz) throws IntrospectionException
    {
        PropertyDescriptor pd = new PropertyDescriptor(propName, clazz);
        return pd.getWriteMethod();
    }
    
    /**
     * 获取propName的Getter
     * @param propName
     * @param clazz
     * @return
     * @throws IntrospectionException
     */
    public static Method getPropertyGetMethod(String propName, Class<?> clazz) throws IntrospectionException
    {
        PropertyDescriptor pd = new PropertyDescriptor(propName, clazz);
        return pd.getReadMethod();
    }
    
}
